package com.example.demo.QRcode;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
public class CreatQRcode {
    private static final Logger log = LoggerFactory.getLogger(CreatQRcode.class);
    private static final int QR_CODE_SIZE = 250;
    private static final String IMAGE_FORMAT = "png";

    /**
     * 生成实时显示二维码方法
     *
     * @param url 传入url
     * @return 包含url的二维码
     * @throws WriterException 如果写入二维码发生错误
     * @throws IOException     如果输出流出现问题
     */
    public ResponseEntity<byte[]> createQRCode(String url) throws WriterException, IOException {
        Map<EncodeHintType, ErrorCorrectionLevel> hintMap = new HashMap<>();
        hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);

        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(url, BarcodeFormat.QR_CODE, QR_CODE_SIZE, QR_CODE_SIZE, hintMap);

        BufferedImage image = createImage(bitMatrix);

        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            ImageIO.write(image, IMAGE_FORMAT, outputStream);
            byte[] imageBytes = outputStream.toByteArray();

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.IMAGE_PNG);

            log.info("QR code generated successfully for URL: {}", url);
            return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
        } catch (IOException e) {
            log.error("Error writing QR code to output stream", e);
            throw e;
        }
    }

    /**
     * 根据BitMatrix创建BufferedImage
     *
     * @param bitMatrix 二维码BitMatrix
     * @return BufferedImage
     */
    private BufferedImage createImage(BitMatrix bitMatrix) {
        int matrixWidth = bitMatrix.getWidth();
        BufferedImage image = new BufferedImage(matrixWidth, matrixWidth, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = (Graphics2D) image.getGraphics();
        drawMatrix(graphics, bitMatrix, matrixWidth);
        graphics.dispose();
        return image;
    }

    /**
     * 在Graphics2D上绘制二维码
     *
     * @param graphics    Graphics2D对象
     * @param bitMatrix   二维码BitMatrix
     * @param matrixWidth 矩阵宽度
     */
    private void drawMatrix(Graphics2D graphics, BitMatrix bitMatrix, int matrixWidth) {
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, matrixWidth, matrixWidth);
        graphics.setColor(Color.BLACK);

        for (int i = 0; i < matrixWidth; i++) {
            for (int j = 0; j < matrixWidth; j++) {
                if (bitMatrix.get(i, j)) {
                    graphics.fillRect(i, j, 1, 1);
                }
            }
        }
    }
}
